package com.tcs.exp;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

import com.tcs.tsrm.beans.Cluster;

public class CoinClustersQuality {
	private HashMap<Integer, double[]> originalMatHash;
	private ArrayList<Cluster> clusterSet;
	private String sensorName;
	private String motifWidth;
	private String algorithm;
	private ArrayList<Double> interClusterMeanEucDist;

	/**
	 * @param sensorName
	 * @param motifWidth
	 * @param algorithm
	 * @param clusterSet
	 * @param originalMatHash
	 */
	public CoinClustersQuality(String sensorName, String motifWidth,
			String algorithm, ArrayList<Cluster> clusterSet,
			HashMap<Integer, double[]> originalMatHash) {
		this.originalMatHash = new HashMap<Integer, double[]>();
		this.clusterSet = new ArrayList<Cluster>();
		this.interClusterMeanEucDist = new ArrayList<Double>();
		this.algorithm = algorithm;
		this.clusterSet = clusterSet;
		this.motifWidth = motifWidth;
		this.sensorName = sensorName;
		this.originalMatHash = originalMatHash;
		this.interClusterMeanEucDist = getAllMeanEucDist();

	}

	public ArrayList<Cluster> getClusterSet() {
		return clusterSet;
	}

	public String getSensorName() {
		return sensorName;
	}

	public String getMotifWidth() {
		return motifWidth;
	}

	public String getAlgorithm() {
		return algorithm;
	}

	public double getMaxEucDist() {
		double maxEucDist = interClusterMeanEucDist.get(0);
		for (Double eachDist : interClusterMeanEucDist) {
			if (eachDist > maxEucDist) {
				maxEucDist = eachDist;
			}
		}
		return maxEucDist;
	}

	public double getMeanEucDist() {
		double eucDistSum = 0;
		for (Double eachDist : interClusterMeanEucDist) {
			eucDistSum += eachDist;
		}
		return eucDistSum / interClusterMeanEucDist.size();
	}

	public double[] getMedianEucDist() {
		double[] median;
		Collections.sort(interClusterMeanEucDist);
		int size = interClusterMeanEucDist.size();
		if ((size % 2) == 0) {
			median = new double[2];
			median[0] = interClusterMeanEucDist.get((size / 2) - 1);
			median[1] = interClusterMeanEucDist.get(size / 2);
		} else {
			median = new double[1];
			median[0] = interClusterMeanEucDist.get(size / 2);
		}
		return median;
	}

	private double calMeanEucDist(ArrayList<double[]> allPoints) {
		double eucDistSum = 0;
		double tempDist = 0;
		for (int i = 0; i < allPoints.size(); i++) {
			for (int j = i + 1; j < allPoints.size(); j++) {
				tempDist = getEucDist(allPoints.get(i), allPoints.get(j));
				eucDistSum += tempDist;
			}
		}
		return eucDistSum / allPoints.size();
	}

	private double getEucDist(double[] point1, double[] point2) {
		double squaredSum = 0;
		for (int i = 0; i < point1.length; i++) {
			squaredSum += Math.pow((point1[i] - point2[i]), 2);
		}
		return Math.sqrt(squaredSum);
	}

	private ArrayList<Double> getAllMeanEucDist() {
		ArrayList<Double> interClusterMeanEucDist = new ArrayList<Double>();
		for (Cluster eachCluster : clusterSet) {
			ArrayList<double[]> allPoints = new ArrayList<double[]>();
			ArrayList<Integer> originalMatIndex = eachCluster
					.getOriginalMatrixIndexes();
			for (Integer index : originalMatIndex) {
				double[] aPoint = originalMatHash.get(index);
				allPoints.add(aPoint);
			}
			double meanEucDist = calMeanEucDist(allPoints);
			interClusterMeanEucDist.add(meanEucDist);
		}
		return interClusterMeanEucDist;
	}
}
